package com.cbgolf.oa.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.text.TextPaint;
import android.view.View;
import butterknife.ButterKnife;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MultiPointItem;
import com.amap.api.maps.model.MultiPointOverlay;
import com.amap.api.maps.model.MultiPointOverlayOptions;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.maps.model.PolylineOptions;
import com.cbgolf.oa.R;
import com.cbgolf.oa.app.App;
import com.cbgolf.oa.app.AppManager;
import com.cbgolf.oa.entity.LatLon;
import com.cbgolf.oa.entity.ParkBean;
import com.cbgolf.oa.entity.ParkFair;
import com.cbgolf.oa.entity.ParkWayInfo;
import com.cbgolf.oa.manager.DataManager;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by lq on 2018/5/4.
 */

public class MapUtil {

  public static final int ZOOM_LEVEL = 15;

  // 功能：判断点是否在多边形内
  // 方法：求解通过该点的水平线与多边形各边的交点
  // 结论：单边交点为奇数，成立!
  //参数：
  // POINT p   指定的某个点
  // LPPOINT ptPolygon 多边形的各个顶点坐标（首末点可以不一致）
  public static boolean isInRange(LatLng point, List<LatLng> APoints) {
    if (Util.listIsNull(APoints)) {
      return false;
    }
    int nCross = 0;
    for (int i = 0; i < APoints.size(); i++) {
      LatLng p1 = APoints.get(i);
      LatLng p2 = APoints.get((i + 1) % APoints.size());
      // 求解 y=p.y 与 p1p2 的交点
      if (p1.longitude == p2.longitude)      // p1p2 与 y=p0.y平行
      {
        continue;
      }
      if (point.longitude < Math.min(p1.longitude, p2.longitude))   // 交点在p1p2延长线上
      {
        continue;
      }
      if (point.longitude >= Math.max(p1.longitude, p2.longitude))   // 交点在p1p2延长线上
      {
        continue;
      }
      // 求交点的 X 坐标 --------------------------------------------------------------
      double x = (double) (point.longitude - p1.longitude) * (double) (p2.latitude - p1.latitude)
          / (double) (p2.longitude - p1.longitude) + p1.latitude;
      if (x > point.latitude) {
        nCross++; // 只统计单边交点
      }
    }
    // 单边交点为偶数，点在多边形之外 ---
    return (nCross % 2 == 1);
  }

  public static List<LatLng> getListLatlngRange(LatLng latLng1, LatLng latLng2) {
    if (null == latLng1 || null == latLng2) {
      return null;
    }
    List<LatLng> list = new ArrayList<>();
    double leftUpLng = latLng1.longitude;
    double leftUpLat = latLng1.latitude;
    double rightDownLng = latLng2.longitude;
    double rightDownLat = latLng2.latitude;
    double leftDownLat = rightDownLat;
    double leftDownLng = leftUpLng;
    double rightUpLat = leftUpLat;
    double rightUpLng = rightDownLng;
    list.add(new LatLng(leftUpLat, leftUpLng));
    list.add(new LatLng(leftDownLat, leftDownLng));
    list.add(new LatLng(rightDownLat, rightDownLng));
    list.add(new LatLng(rightUpLat, rightUpLng));
    return list;
  }

  public static List<LatLng> getListLatlngRange(ParkBean mData) {

    if (null == mData || null == mData.courseFairwayInfo
        || null == mData.courseFairwayInfo.leftUpPoints
        || null == mData.courseFairwayInfo.rightDownPoints) {
      return null;
    }
    List<LatLng> list = new ArrayList<>();
    try {
      double leftUpLng = TypeUtil.parseDauble(mData.courseFairwayInfo.leftUpPoints.lng);
      double leftUpLat = TypeUtil.parseDauble(mData.courseFairwayInfo.leftUpPoints.lat);
      double rightDownLng = TypeUtil.parseDauble(mData.courseFairwayInfo.rightDownPoints.lng);
      double rightDownLat = TypeUtil.parseDauble(mData.courseFairwayInfo.rightDownPoints.lat);
      double leftDownLat = rightDownLat;
      double leftDownLng = leftUpLng;
      double rightUpLat = leftUpLat;
      double rightUpLng = rightDownLng;
      list.add(new LatLng(leftUpLat, leftUpLng));
      list.add(new LatLng(leftDownLat, leftDownLng));
      list.add(new LatLng(rightDownLat, rightDownLng));
      list.add(new LatLng(rightUpLat, rightUpLng));
    } catch (Exception e) {

    }
    return list;
  }

  public static LatLng getCenterLatLng(LatLng latLng, LatLng latLng1) {
    return getCenterLatLng(latLng.latitude, latLng.longitude, latLng1.latitude, latLng1.longitude);
  }

  public static LatLng getCenterLatLng(double lat1, double lng1, double lat2, double lng2) {
    return new LatLng((lat1 + lat2) / 2D, (lng1 + lng2) / 2D);
  }

  public static LatLng getCovertLatlng(LatLon latLng) {
    return new LatLng(TypeUtil.parseDauble(latLng.lat), TypeUtil.parseDauble(latLng.lng));
  }

  public static List<LatLng> getCovertList(List<LatLon> list) {
    List<LatLng> listLatlng = new ArrayList<>();
    if (!Util.listIsNull(list)) {
      LatLng latLng;
      for (int i = 0; i < list.size(); i++) {
        latLng = new LatLng(TypeUtil.parseDauble(list.get(i).lat),
            TypeUtil.parseDauble(list.get(i).lng));
        listLatlng.add(latLng);
      }
    }
    return listLatlng;

  }

  /**
   * 转换球道经纬度数据
   */
  public static List<ParkWayInfo> getCovertListWayInfo(ParkBean mData) {
    List<ParkWayInfo> listWayInfo = new ArrayList<>();
    if (null != mData && null != mData.courseFairwayInfo) {
      ParkWayInfo info;
      List<ParkFair> listWays = mData.courseFairwayInfo.fairwayInfo;
      for (int i = 0; i < listWays.size(); i++) {
        info = new ParkWayInfo();
        info.fairwayName = listWays.get(i).fairwayName;
        info.fairwayPoints = MapUtil.getCovertList(listWays.get(i).fairwayPoints);
        listWayInfo.add(info);
      }
    }
    return listWayInfo;
  }

  /**
   * 转换球道经纬度数据
   */
  public static List<List<LatLng>> geListAllLatlng(List<ParkFair> listWays) {
    List<List<LatLng>> listAll = new ArrayList<>();
    for (int i = 0; i < listWays.size(); i++) {
      List<LatLng> list = MapUtil.getCovertList(listWays.get(i).fairwayPoints);
      listAll.add(list);
    }
    return listAll;
  }

  /**
   * 球道多边形
   */
  public static Polygon drawPolygon(AMap aMap, List<LatLng> list) {
    PolygonOptions polygonOptions = new PolygonOptions();
    LatLng latLng;
    for (int j = 0; j < list.size(); j++) {
      latLng = new LatLng(list.get(j).latitude, list.get(j).longitude);
      polygonOptions.add(latLng);
    }
    polygonOptions.addAll(polygonOptions.getPoints());
    polygonOptions.strokeWidth(6) // 多边形的边框
        .strokeColor(Color.argb(255, 192, 198, 191)) // 边框颜色
        .fillColor(Color.argb(125, 229, 79, 85))
        .visible(true);   // 多边形的填充色
    Polygon polygon = aMap.addPolygon(polygonOptions);
    return polygon;
  }

  /**
   * 画球道轮廓
   */
  public static void drawWays(AMap aMap, List<LatLng> latLngs) {
    if (null == aMap || Util.listIsNull(latLngs)) {
      return;
    }
    aMap.addPolyline(new PolylineOptions().
        addAll(latLngs)
        .width(15)
        .color(Color.argb(255, 229, 79, 85))
        .setUseTexture(true));
  }

  /**
   * 添加海量图标
   *
   * @param type 对应球僮 ，工作人员，打球人
   * @param bean 数据集合
   * @param listRange 球场范围
   */
  public static MultiPointOverlay drawMakers(AMap aMap, int type, ParkBean bean,
      List<LatLng> listRange) {
    if (null == aMap || null == bean) {
      return null;
    }
    MultiPointOverlayOptions overlayOptions = new MultiPointOverlayOptions();
    //设置图标
    overlayOptions.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory
        .decodeResource(App.getContext().getResources(), getMakerIcon(type))));
    //设置锚点
    overlayOptions.anchor(0.5f, 0.5f);
    MultiPointOverlay multiPointOverlay = aMap.addMultiPointOverlay(overlayOptions);
    List<MultiPointItem> listPoint = new ArrayList<>();
//    String tag = getTag(type);
    List<LatLng> listLatlng = getListLatlng(type, bean);
    List<LatLon> listInfo = getListLatInfo(type, bean);
    LatLng latLng;
    for (int i = 0; i < listLatlng.size(); i++) {
//      if (isInRange(listLatlng.get(i), listRange)) {
      latLng = new LatLng(listLatlng.get(i).latitude, listLatlng.get(i).longitude);
      //创建MultiPointItem存放，海量点中某单个点的位置及其他信息
      MultiPointItem multiPointItem = new MultiPointItem(latLng);
      if (!Util.listIsNull(listInfo)) {
        try {
          multiPointItem
              .setCustomerId(String.valueOf(type));
          multiPointItem.setTitle(listInfo.get(i).userName);
          multiPointItem.setObject(listInfo.get(i));
        } catch (Exception e) {

        }
//        }
        listPoint.add(multiPointItem);
      }
    }
    //将规范化的点集交给海量点管理对象设置，待加载完毕即可看到海量点信
    multiPointOverlay.setItems(listPoint);
    return multiPointOverlay;
  }

  private static List<LatLng> getListLatlng(int type, ParkBean bean) {
    if (null == bean) {
      return null;
    }
    List<LatLng> list;
    switch (type) {
      case DataManager.CADDIE:
        list = bean.listCaddieLatLng;
        break;
      case DataManager.PLAYER:
        list = bean.listPlayerLatLng;
        break;
      case DataManager.WORKER:
        list = bean.listWorderLatlng;
        break;
      default:
        list = bean.listCaddieLatLng;
        break;
    }
    return list;
  }

  private static List<LatLon> getListLatInfo(int type, ParkBean bean) {
    if (null == bean) {
      return null;
    }
    List<LatLon> list;
    switch (type) {
      case DataManager.CADDIE:
        list = bean.listCaddie;
        break;
      case DataManager.PLAYER:
        list = bean.listPlayer;
        break;
      case DataManager.WORKER:
        list = bean.listWorder;
        break;
      default:
        list = bean.listCaddie;
        break;
    }
    return list;
  }

  public static void removePoints(List<MultiPointOverlay> list) {
    if (!Util.listIsNull(list)) {
      for (int i = 0; i < list.size(); i++) {
        if (null != list.get(i)) {
          list.get(i).remove();
//          list.get(i).destroy();
        }
      }
      list.clear();
    }
  }

  /**
   * 添加海量图标
   *
   * @param type 对应球僮 ，工作人员，打球人
   * @param list 海量点集合
   * @param listRange 球场范围
   */
  public static MultiPointOverlay drawMakers(AMap aMap, int type, List<LatLng> list,
      List<LatLng> listRange) {
    if (null == aMap || Util.listIsNull(list)) {
      return null;
    }
    MultiPointOverlayOptions overlayOptions = new MultiPointOverlayOptions();
    //设置图标
    overlayOptions.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory
        .decodeResource(App.getContext().getResources(), getMakerIcon(type))));
    //设置锚点
    overlayOptions.anchor(0.5f, 0.5f);
    MultiPointOverlay multiPointOverlay = aMap.addMultiPointOverlay(overlayOptions);
    List<MultiPointItem> listPlayer = new ArrayList<>();
    String tag = getTag(type);
    LatLng latLng;
    for (int i = 0; i < list.size(); i++) {
//      if (MapUtil.isPointInPolygon(list.get(i), listRange)) {
      latLng = new LatLng(list.get(i).latitude,
          list.get(i).longitude);
      //创建MultiPointItem存放，海量点中某单个点的位置及其他信息
      MultiPointItem multiPointItem = new MultiPointItem(latLng);
//      if (!Util.listIsNull(listInfo)) {
//        try {
//          multiPointItem.setCustomerId(listInfo.get(i).identityType);
//          multiPointItem.setTitle(listInfo.get(i).userName);
//          multiPointItem.setObject(listInfo.get(i));
//        } catch (Exception e) {
//
//        }
      listPlayer.add(multiPointItem);
    }
    //将规范化的点集交给海量点管理对象设置，待加载完毕即可看到海量点信
    multiPointOverlay.setItems(listPlayer);
    return multiPointOverlay;
  }

  public static void drawTextMaker(AMap aMap, ParkBean bean) {
    if (null == bean || null == bean.courseFairwayInfo
        || Util.listIsNull(bean.courseFairwayInfo.fairwayInfo)) {
      return;
    }
    for (int i = 0; i < bean.courseFairwayInfo.fairwayInfo.size(); i++) {
      if (null == bean.courseFairwayInfo.fairwayInfo.get(i).centerPoint) {
        continue;
      }
      drawTextMaker(aMap, new LatLng(
              TypeUtil.parseDauble(bean.courseFairwayInfo.fairwayInfo.get(i).centerPoint.lat),
              TypeUtil.parseDauble(bean.courseFairwayInfo.fairwayInfo.get(i).centerPoint.lng)
          ),
          bean.courseFairwayInfo.fairwayInfo.get(i).fairwayName
      );
    }

  }

  public static void drawTextMaker(AMap aMap, LatLng latLng, String text) {
    if (null == aMap || Util.isNull(text)) {
      return;
    }
    View makerView = getMakerView(text);
    Marker localMarker = aMap.addMarker(new MarkerOptions()
        .position(latLng)
        .icon(null != makerView ?
            BitmapDescriptorFactory.fromView(makerView)
            : BitmapDescriptorFactory.fromBitmap(getTextBitmap(text))));
    localMarker.setObject(text);
  }

  //getMyBitmap方法：
  public static View getMakerView(String text) {
    View view = ViewUtils
        .inflate(AppManager.getNewInstance().currentActivity(), R.layout.maker_text);
    if (null == view) {
      return view;
    }
    ViewUtils.setText(ButterKnife.findById(view, R.id.tv_maker), text);
    return view;
  }

  //getMyBitmap方法：
  public static Bitmap getTextBitmap(String text) {
    Bitmap bitmap = BitmapDescriptorFactory.fromResource(
        R.drawable.bg_transparent).getBitmap();
    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
        bitmap.getHeight());
    Canvas canvas = new Canvas(bitmap);
    TextPaint textPaint = new TextPaint();
    textPaint.setAntiAlias(true);
    textPaint.setTextSize(25f);
    textPaint.setColor(
        ContextCompat.getColor(App.getContext(), R.color.text_red));
    canvas.drawText(text, 17, 35, textPaint);// 设置bitmap上面的文字位置
    return bitmap;
  }

  public static int getMakerIcon(int type) {
    int drawRes = R.mipmap.caddie_maker;
    switch (type) {
      case DataManager.CADDIE:
        drawRes = R.mipmap.caddie_maker;
        break;
      case DataManager.PLAYER:
        drawRes = R.mipmap.player_tag;
        break;
      case DataManager.WORKER:
        drawRes = R.mipmap.worker_maker;
        break;
      default:
        break;
    }
    return drawRes;
  }

  private static String getTag(int type) {
    String tag = "caddie";
    switch (type) {
      case DataManager.PLAYER:
        tag = "player";
        break;
      case DataManager.WORKER:
        tag = "worker";
        break;
      default:
        break;
    }
    return tag;
  }

  public static void showLocation(AMap aMap) {
    if (null == aMap) {
      return;
    }
    // 设置定位的类型为定位模式，有定位、跟随或地图根据面向方向旋转几种
//    MyLocationStyle myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）如果不设置myLocationType，默认也会执行此种模式。
//    myLocationStyle
//        .interval(2000); //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
//    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW);
//    myLocationStyle.anchor(0.5f, 0.5f);//设置定位蓝点图标的锚点方法。
//    myLocationStyle.showMyLocation(true);
//    aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
////aMap.getUiSettings().setMyLocationButtonEnabled(true);设置默认定位按钮是否显示，非必需设置。
//    aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不

//    初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）如果不设置myLocationType，默认也会执行此种模式。
//    MyLocationStyle myLocationStyle = new MyLocationStyle();
//    //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
//    myLocationStyle.interval(2000);
//    aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
//    aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示，非必需设置。
//    aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
//    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);//只定位一次。
//    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE) ;//定位一次，且将视角移动到地图中心点。
//    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW) ;//连续定位、且将视角移动到地图中心点，定位蓝点跟随设备移动。（1秒1次定位）
//    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_MAP_ROTATE);//连续定位、且将视角移动到地图中心点，地图依照设备方向旋转，定位点会跟随设备移动。（1秒1次定位）
//    myLocationStyle.myLocationType(
//        MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）默认执行此种模式。
////以下三种模式从5.1.0版本开始提供
////    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);//连续定位、蓝点不会移动到地图中心点，定位点依照设备方向旋转，并且蓝点会跟随设备移动。
////    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);//连续定位、蓝点不会移动到地图中心点，并且蓝点会跟随设备移动。
////    myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_MAP_ROTATE_NO_CENTER);//连续定位、蓝点不会移动到地图中心点，地图依照设备方向旋
//    myLocationStyle.showMyLocation(true);
//    设置是否显示定位小蓝点，用于满足只想使用定位，不想使用定位小蓝点的场景，设置false以后图面上不再有定位蓝点的概念，但是会持续回调位置信息。
//    myLocationStyle.myLocationIcon(BitmapDescriptor myLocationIcon);//设置定位蓝点的icon图标方法，需要用到BitmapDescriptor类对象作为参数。
  }

  public static void hideLocation(AMap aMap) {
    if (null == aMap) {
      return;
    }
    aMap.getUiSettings().setMyLocationButtonEnabled(false);
    // 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
    aMap.setMyLocationEnabled(false);
  }

  /**
   * 移动地图中心点到两点中心
   */
  public static void moveToAreaCenter(AMap aMap, LatLng ll1, LatLng ll2) {
    if (null == aMap) {
      return;
    }
    LatLng center = MapUtil.getCenterLatLng(ll1, ll2);
//    aMap.moveCamera(CameraUpdateFactory.changeLatLng(latLng));
//    aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
    aMap.moveCamera(CameraUpdateFactory.newCameraPosition(
        new CameraPosition(center,//新的中心点坐标
            MapUtil.ZOOM_LEVEL, //新的缩放级别
            30, //俯仰角0°~45°（垂直与地图时为0）
            0  ////偏航角 0~360° (正北方为0)
        )));
//    aMap.moveCamera(CameraUpdateFactory.zoomTo(MapUtil.ZOOM_LEVEL));

  }

  /**
   * 移动地图中心点到两点中心
   */
  public static void moveToAreaNoZoom(AMap aMap, LatLng ll1, LatLng ll2) {
    if (null == aMap) {
      return;
    }
    LatLng center = MapUtil.getCenterLatLng(ll1, ll2);
    aMap.moveCamera(CameraUpdateFactory.changeLatLng(center));
//    aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
//    aMap.moveCamera(CameraUpdateFactory.newCameraPosition(
//        new CameraPosition(center,//新的中心点坐标
//            MapUtil.ZOOM_LEVEL, //新的缩放级别
//            30, //俯仰角0°~45°（垂直与地图时为0）
//            0  ////偏航角 0~360° (正北方为0)
//        )));
//    aMap.moveCamera(CameraUpdateFactory.zoomTo(MapUtil.ZOOM_LEVEL));

  }

}
